package cn.xn.hrms.domain.service.impl;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import cn.xn.hrms.api.dto.res.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;

import cn.xn.hrms.domain.enums.ResultEnum;
import cn.xn.hrms.domain.exception.BaseException;
import cn.xn.hrms.domain.service.MenuService;
import cn.xn.hrms.infrastructure.dao.MenuDao;
import cn.xn.hrms.infrastructure.dao.RoleMenuDao;
import cn.xn.hrms.infrastructure.dao.UserRoleDao;
import lombok.extern.slf4j.Slf4j;

/**
 * @author: ysz
 * @date: 2023/07/24
 **/
@Service
@Slf4j
public class MenuServiceImpl implements MenuService {


    @Resource
    private UserRoleDao userRoleDao;

    @Resource
    private RoleMenuDao roleMenuDao;

    @Resource
    private MenuDao menuDao;

    @Override
    public UserMenuDTO getUserMenuList() {

        UserDTO userDTO = (UserDTO) SecurityUtils.getSubject().getPrincipal();
        // 设置默认菜单，每个用户都有
        UserMenuDTO userMenuDTO = new UserMenuDTO();
        // 设置默认项
        MenuDTO homeMenu = new MenuDTO();
        homeMenu.setTitle("首页");
        homeMenu.setHref("page/welcome.html");
        MenuDTO loginMenu = new MenuDTO();
        loginMenu.setTitle("悦掌科技");
        loginMenu.setHref("/index.html");
        loginMenu.setImage("/layuimini/images/logo.jpeg");

        userMenuDTO.setHomeInfo(homeMenu);
        userMenuDTO.setLogoInfo(loginMenu);
        List<UserRoleDTO> userRoleList = userRoleDao.findAllByUserId(userDTO.getUserId().longValue());
        if (CollectionUtils.isNotEmpty(userRoleList)) {
            // 角色菜单
            List<Long> roleIds = userRoleList.stream().map(UserRoleDTO::getRoleId).distinct().collect(Collectors.toList());
            List<RoleMenuDTO> roleMenuList = roleMenuDao.findAllByRoleIdIn(roleIds);
            if (CollectionUtils.isNotEmpty(roleMenuList)) {
                List<Long> menuIds = roleMenuList.stream().map(RoleMenuDTO::getMenuId).distinct().collect(Collectors.toList());
                // 菜单
                List<MenuDTO> menuList = menuDao.findAllByIdIn(menuIds);
                // 递归查找每一个菜单下的子菜单
                List<Menu> menuInfo = transferMenu(menuList, 0L);
                // 排序
                List<Menu> sortedList =
                        menuInfo.stream()
                                // sort字段升序
                                .sorted(Comparator.comparing(Menu::getSort))
                                .collect(Collectors.toList());
                userMenuDTO.setMenuInfo(sortedList);

            }
        }

        return userMenuDTO;
    }

    /**
     * 封装菜单视图
     * @param allMenu
     * @param parentId
     * @return
     */
    private List<Menu> transferMenu(List<MenuDTO> allMenu, Long parentId){
        List<Menu> resultList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(allMenu)){
            for (MenuDTO source : allMenu) {
                if(parentId.longValue() == source.getParentMenuId().longValue()){
                    Menu menu = new Menu();
                    BeanUtils.copyProperties(source, menu);
                    //递归查询子菜单，并封装信息
                    List<Menu> childList = transferMenu(allMenu, source.getMenuId());
                    if(!CollectionUtils.isEmpty(childList)){
                        menu.setChild(childList);
                    }
                    resultList.add(menu);
                }
            }
        }
        return resultList;
    }


    @Override
    public List<MenuChildDTO> getMenuList(Long roleId) {

        List<MenuDTO> menuList = menuDao.findAll();

        Map<Long, RoleMenuDTO> roleMenuMap = Maps.newHashMap();
        if (null != roleId) {
            List<RoleMenuDTO> roleMenuList = roleMenuDao.findAllByRoleIdIn(Arrays.asList(roleId));
            if (!CollectionUtils.isEmpty(roleMenuList)) {
                Map<Long, RoleMenuDTO> map = roleMenuList.stream().collect(Collectors.toMap(RoleMenuDTO::getMenuId,
                        Function.identity(), (v1, v2) -> v2));
                roleMenuMap.putAll(map);

            }
        }
        return recursionMenu(menuList, 0L, roleMenuMap);


    }


    private List<MenuChildDTO> recursionMenu(List<MenuDTO> allMenu, Long parentId, Map<Long, RoleMenuDTO> roleMenuMap){
        List<MenuChildDTO> resultList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(allMenu)){

            Map<Long, MenuDTO> map = allMenu.stream().collect(Collectors.toMap(MenuDTO::getMenuId, Function.identity(),
                    (v1, v2) -> v2));
            for (MenuDTO source : allMenu) {
                if(parentId.longValue() == source.getParentMenuId().longValue()){
                    MenuChildDTO menu = new MenuChildDTO();
                    BeanUtils.copyProperties(source, menu);
                    if (null != menu.getParentId() && menu.getParentId().intValue() != 0) {
                        MenuDTO parentMenu = map.get(menu.getParentId());
                        if (null != parentMenu) {
                            menu.setParentName(parentMenu.getTitle());
                        }
                    }
                    if (MapUtils.isNotEmpty(roleMenuMap)) {
                        RoleMenuDTO roleMenu = roleMenuMap.get(menu.getId());
                        if (null != roleMenu) {
                            menu.setChecked(Boolean.TRUE);
                        }
                    }
                    //递归查询子菜单，并封装信息
                    List<MenuChildDTO> childList = recursionMenu(allMenu, source.getMenuId(), roleMenuMap);
                    if(!CollectionUtils.isEmpty(childList)){
                        menu.setChildren(childList);
                    }
                    resultList.add(menu);
                }
            }
        }
        return resultList;
    }


    @Override
    public void add(MenuDTO menuDTO) {
        log.info("新增菜单,{}", JSON.toJSONString(menuDTO));
        menuDTO.setParentMenuId(0L);
        if (null !=menuDTO.getParentId()) {
            menuDTO.setParentMenuId(menuDTO.getParentId());
        }
        menuDTO.setTarget("_self");
        menuDao.insertSelective(menuDTO);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteMenu(Long id) {

        //如果菜单下面有子菜单，不允许删除
        Long count = menuDao.countByParentId(id);
        if (count != null && count.intValue() > 0) {
            throw new BaseException(ResultEnum.MENU_DELETE_ERROR);
        }
        menuDao.updateIsDeletedById(1, id);
        // 删除菜单之后，需要删除角色菜单映射
        roleMenuDao.updateIsDeletedByMenuId(1, id);
    }

    @Override
    public void update(MenuDTO menuDTO) {
        menuDTO.setMenuId(menuDTO.getId());
        menuDTO.setParentMenuId(menuDTO.getParentId());
        menuDao.updateByPrimaryKeySelective(menuDTO);
    }

}
